package com.javasm.service;


import com.alibaba.fastjson.JSONObject;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;

/**
     * 模仿 UsernamePasswordAuthenticationFilter 获取前端传递的 手机号、验证码
     */
    public class PhoneNumAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

        // 表示这个 Filter 拦截 /phone/login 接口
        private static final AntPathRequestMatcher DEFAULT_ANT_PATH_REQUEST_MATCHER =
                new AntPathRequestMatcher("/phone/login", "POST");

        // 参数名
        private String phoneParameter = "phone";
        private String numParameter = "num";


        public PhoneNumAuthenticationFilter() {
            super(DEFAULT_ANT_PATH_REQUEST_MATCHER);
        }

        /**
         * 用来获取前端传递的手机号和验证码，然后调用 authenticate 方法进行认证
         * @param request
         * @param response
         * @return
         * @throws AuthenticationException
         * @throws IOException
         * @throws ServletException
         */
        @Override
        public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
            if (!"POST".equals(request.getMethod())) {
                throw new AuthenticationServiceException("请求方式有误: " + request.getMethod());
            }
            //如果请求的参数格式不是json，直接异常
            if (!request.getContentType().equals(MediaType.APPLICATION_JSON_VALUE)){
                throw new AuthenticationServiceException("参数不是json：" + request.getMethod());
            }
            // 用户以json的形式传参的情况下
            String phone = null;
            String num = null;
            try {
                Map<String,String> map = JSONObject.parseObject(request.getInputStream(),Map.class);
                phone = map.get(phoneParameter);
                num = map.get(numParameter);
            } catch (IOException e) {
                throw new AuthenticationServiceException("参数不对：" + request.getMethod());
            }

            if (phone == null) {
                phone = "";
            }
            if (num == null) {
                num = "";
            }

            phone = phone.trim();
            // 封装手机号、验证码，后面框架会从中拿到 手机号， 调用我们的 LoginPhoneService 获取用户
            PhoneNumAuthenticationToken authRequest
                    = new PhoneNumAuthenticationToken(phone, num);
            //设置ip、sessionId信息
            setDetails(request,authRequest);
            return this.getAuthenticationManager().authenticate(authRequest);
        }


        //在哪调用这个方法了？
        protected void setDetails(HttpServletRequest request, PhoneNumAuthenticationToken authRequest) {
            authRequest.setDetails(this.authenticationDetailsSource.buildDetails(request));
        }
    }

